/**
 * zoneland.net Inc.
 * Copyright (c) 2002-2013 All Rights Reserved.
 */
package net.zoneland.knowledge.utils;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import net.zoneland.knowledge.model.TreeNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 树形构造器
 * <P>
 * 每个需要构建树形的类，需要实现toTree的方法，把对象转化成{@link TreeNode}对象
 * </p>
 * 
 * @author ypz
 * @version $Id: TreeBuilder.java, v 0.1 2013-5-9 下午4:07:32 ypz Exp $
 */
public class TreeBuilder {

    private static final Logger logger = LoggerFactory.getLogger(TreeBuilder.class);

    /**
     * 构建树形结构，返回根节点
     *
     * @param objectList
     *            需要构建的原始列表
     * @param topId
     *            根节点ID，如果没有可以传入null
     * @return 根节点
     */
    public static <T> TreeNode<T> createTree(List<T> objectList, String topId) {
        return createTree(objectList, topId, false);
    }

    /**
     * 构建树形结构，返回根节点
     *
     * @param objectList
     *            需要构建的原始列表
     * @param topId
     *            根节点ID，如果没有可以传入null
     * @param addToTop
     *            父节点找不到是否加到Top下作为Top的子节点
     * @return 根节点
     */
    @SuppressWarnings("unchecked")
    public static <T> TreeNode<T> createTree(List<T> objectList, String topId, boolean addToTop) {
        TreeNode<T> top = new TreeNode<T>();
        if (topId == null) {
            topId = "";
        }
        top.setChecked(false);
        top.setId(topId);
        if (objectList != null && objectList.size() > 0) {
            Map<String, TreeNode<T>> resMap = new HashMap<String, TreeNode<T>>();
            List<TreeNode<T>> treeList = new ArrayList<TreeNode<T>>(objectList.size());// 用于排序
            boolean isIncludeTop = false;
            for (Object object : objectList) {
                TreeNode<T> child = (TreeNode<T>) objectToTree(object);
                if (child != null) {
                    String id = child.getId();
                    if (child.getTitle() != null && child.getData() == null) {
                        id = child.getTitle();
                    }
                    if (id.contains("~")) {
                        String[] idArr = id.split("~");
                        if (null != idArr && idArr.length > 0) {
                            id = idArr[1];
                        }
                    }
                    resMap.put(id, child);
                    treeList.add(child);
                    if (topId.equals(id)) {
                        isIncludeTop = true;
                        top = child;
                    }
                }
            }
            // 如果List中已经包含了根节点，就不需要再加入了
            if (!isIncludeTop) {
                resMap.put(topId, top);
            }
            // 遍历TreeList，创建tree
            for (TreeNode<T> child : treeList) {
                // 排除根节点
                if (!topId.equals(child.getId())) {
                    TreeNode<T> parent = resMap.get(child.getpId());
                    // 如果找不到上级节点，根据addToTop决定是否加入
                    if (parent != null) {
                        // parent = top;
                        parent.getChildren().add(child);
                    } else if (addToTop == true) {
                        top.getChildren().add(child);
                    }
                }
            }
        }
        // 确认当前节点是否有子对象，若有则此节点不允许选择。
        /*
         * List<TreeNode<T> > topList=top.getChildren(); for (Iterator<?> iterator =
         * topList.iterator(); iterator.hasNext();) { TreeNode<T> treeNode =
         * (TreeNode<T>) iterator.next(); List<TreeNode<T> >
         * childerList=treeNode.getChildren();
         * if(null!=childerList&&!childerList.isEmpty()){ treeNode.setClickable(false);
         * }else{ treeNode.setClickable(true); } //第二级如果有也不允许 for (Iterator<?> iterator2
         * = childerList.iterator(); iterator2 .hasNext();) { TreeNode<T> SedtreeNode =
         * (TreeNode<T>) iterator2.next(); List<TreeNode<T> >
         * sedchilderList=SedtreeNode.getChildren();
         * if(null!=sedchilderList&&!sedchilderList.isEmpty()){
         * SedtreeNode.setClickable(false); }else{ SedtreeNode.setClickable(true); } } }
         */
        return top;
    }

    /**
     * 将对象转化成 {@link TreeNode} 对象
     * <p>
     * 各个树形类实现toTree方法
     * </p>
     * 
     * @param object
     * @return
     */
    @SuppressWarnings("unchecked")
    private static <T> TreeNode<T> objectToTree(T object) {
        try {
            Method toTreeMethod = object.getClass().getMethod("toTree");
            return (TreeNode<T>) toTreeMethod.invoke(object);
        } catch (SecurityException e) {
            logger.error("获取toTree方法异常", e);
        } catch (NoSuchMethodException e) {
            logger.error("获取toTree方法异常", e);
        } catch (IllegalArgumentException e) {
            logger.error("调用toTree方法异常", e);
        } catch (IllegalAccessException e) {
            logger.error("调用toTree方法异常", e);
        } catch (InvocationTargetException e) {
            logger.error("调用toTree方法异常", e);
        }
        return null;
    }

    @SuppressWarnings("unchecked")
    public static <T> List<TreeNode<T>> objectsToTree(List<T> list) {
        try {
            List<TreeNode<T>> listTreeNode = new ArrayList<TreeNode<T>>();
            for (T object : list) {
                Method toTreeMethod = object.getClass().getMethod("toTree");
                listTreeNode.add((TreeNode<T>) toTreeMethod.invoke(object));
            }
            return listTreeNode;
        } catch (SecurityException e) {
            logger.error("获取toTree方法异常", e);
        } catch (NoSuchMethodException e) {
            logger.error("获取toTree方法异常", e);
        } catch (IllegalArgumentException e) {
            logger.error("调用toTree方法异常", e);
        } catch (IllegalAccessException e) {
            logger.error("调用toTree方法异常", e);
        } catch (InvocationTargetException e) {
            logger.error("调用toTree方法异常", e);
        }
        return null;
    }
}
